﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections;
using System.Threading.Tasks;
using System.Xml;

namespace RAP.Framework.Libary.Utils
{
  /// <summary>
  /// Stream对象扩展
  /// </summary>
  public static partial class Extensions
  {

    /// <summary>
    /// 从指定流对象反序列化为指定类型的对象
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="stream"></param>
    /// <returns></returns>
    public static T Deserialize<T>(this Stream stream)
    {
      BinaryFormatter bf = new BinaryFormatter();
      stream.Seek(0, SeekOrigin.Begin);
      return (T)bf.Deserialize(stream);
    }

    /// <summary>
    /// 将指定的Stream对象读取为JSON字符串并转换层JSON对象
    /// </summary>
    /// <param name="stream"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static IDictionary Eval(this StreamReader stream, object defaultValue = null)
    {
      return stream.ReadToEnd().ToDictionary();
    }

    /// <summary>
    /// 读取指定Stream对象的所有文本内容
    /// </summary>
    /// <param name="stream"></param>
    /// <param name="defaultValue"></param>
    /// <returns></returns>
    public static string ReadAllText(this Stream stream, string defaultValue = null, Encoding enc = null)
    {
      using (var ms = new MemoryStream())
      {
        stream.CopyTo(ms);
        ms.Position = 0;
        using (var reader = new StreamReader(ms, enc.IsNullValue<Encoding>(Encoding.UTF8)))
        {
          return reader.ReadToEnd().TrimStart((char)65279);//去除UTF-8签名的字节
        }
      }
    }

    /// <summary>
    /// 异步读取所有文本内容
    /// </summary>
    /// <param name="stream"></param>
    /// <param name="defaultValue"></param>
    /// <param name="contentLen">内容长度，在未知内容长度，即contentLen=-1（Stream不可Seek时），采用异步Buffer读取</param>
    /// <param name="enc">转换成字符串的编码器</param>
    /// <returns></returns>
    public static async Task<string> ReadAllTextAsync(this Stream stream, string defaultValue = null, Encoding enc = null)
    {
      using (var ms = new MemoryStream())
      {
        stream.CopyTo(ms);
        ms.Position = 0;
        using (var reader = new StreamReader(ms, enc.IsNullValue<Encoding>(Encoding.UTF8)))
        {
          var content = await reader.ReadToEndAsync();
          return content.TrimStart((char)65279);//去除UTF-8签名的字节
        }
      }
    }

    /// <summary>
    /// 将指定的对象持久化到指定的文件中
    /// </summary>
    /// <param name="dataObject"></param>
    /// <param name="filePath"></param>
    public static void Serialize(this object dataObject, string filePath)
    {
      if (File.Exists(filePath))
      {
        File.Delete(filePath);
      }
      BinaryFormatter bf = new BinaryFormatter();
      using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite))
      {
        byte[] fileData;
        using (MemoryStream ms = new MemoryStream())
        {
          bf.Serialize(ms, dataObject);

          ms.Seek(0, SeekOrigin.Begin);
          fileData = new byte[ms.Length];
          ms.Read(fileData, 0, fileData.Length);
        }
        fs.Write(fileData, 0, fileData.Length);
        fs.Close();
      }
      bf = null;
    }

    /// <summary>
    /// 将指定对象序列化称流对象
    /// </summary>
    /// <param name="dataObject"></param>
    /// <returns></returns>
    public static Stream Serialize(this object dataObject)
    {
      BinaryFormatter bf = new BinaryFormatter();
      MemoryStream ms = new MemoryStream();
      bf.Serialize(ms, dataObject);
      return ms;
    }


    /// <summary>
    /// 反序列化指定的文件为对象
    /// </summary>
    /// <param name="dataFile"></param>
    /// <returns></returns>
    public static T Deserialize<T>(this FileInfo dataFile)
    {
      object dataObject;
      BinaryFormatter bf = new BinaryFormatter();
      using (FileStream fs = dataFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
      {
        byte[] fileData = new byte[fs.Length];
        fs.Read(fileData, 0, fileData.Length);
        using (MemoryStream ms = new MemoryStream(fileData))
        {
          dataObject = bf.Deserialize(ms);
        }
      }
      return (T)dataObject;
    }


    /// <summary>
    /// 将指定的Stream对象的数据转换成文本数据
    /// </summary>
    /// <param name="stream">Stream对象</param>
    /// <param name="enc">编码，默认UTF-8</param>
    public static string ToString(this Stream stream, Encoding enc = null)
    {
      stream.Position = 0;
      byte[] arr = new byte[stream.Length];
      stream.Read(arr, 0, arr.Length);
      return (enc != null ? enc : Encoding.UTF8).GetString(arr);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="stream"></param>
    /// <param name="contentLength"></param>
    /// <param name="enc"></param>
    /// <returns></returns>
    public static IDictionary ToDictionary(this Stream stream, int contentLength, Encoding enc = null)
    {
      if (contentLength <= 0)
      {
        return null;
      }

      var resStr = stream.ReadAllText();
      if (resStr.StartsWith("<xml"))
      {
        var xmlDoc = new XmlDocument();
        var resXml = new Hashtable();
        try
        {
          xmlDoc.LoadXml(resStr);
          var xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>
          var nodes = xmlNode.ChildNodes;
          foreach (XmlNode xn in nodes)
          {
            XmlElement xe = (XmlElement)xn;
            resXml[xe.Name] = xe.InnerText;//获取xml的键值对到WxPayData内部的数据中
          }
        }
        catch (Exception e)
        {
          Debug.Err(e);
          return null;
        }
        return resXml;
      }
      else
      {
        //默认传入JSON字符串
        return resStr.ToDictionary();
      }
    }

    /// <summary>
    /// 异步读取流知道流结束
    /// </summary>
    /// <param name="stream"></param>
    /// <param name="enc"></param>
    /// <returns></returns>
    public static async Task<IDictionary> ToDictionary(this Stream stream, Encoding enc = null)
    {
      IList<byte> result = new List<byte>();
      int bytesRead = -1;
      var bufferLen = 512;
      while (bytesRead != 0)
      {
        try
        {
          byte[] buffer = new byte[bufferLen];
          bytesRead = await stream.ReadAsync(buffer, 0, bufferLen);
          if (bytesRead > 0)
          {
            if (bytesRead == bufferLen)
            {
              result.Add(buffer);
            }
            else
            {
              byte[] data = new byte[bytesRead];
              Array.Copy(buffer, data, bytesRead);
              result.Add(data);
            }
          }
        }
        catch (Exception e)
        {
          Debug.Err(e);
          return null;
        }
      }
      string resStr = result.ToArray().ToText(enc: enc);
      if (resStr.StartsWith("<xml"))
      {
        XmlDocument xmlDoc = new XmlDocument();
        IDictionary resXml = new Hashtable();
        try
        {
          xmlDoc.LoadXml(resStr);
          XmlNode xmlNode = xmlDoc.FirstChild;//获取到根节点<xml>
          XmlNodeList nodes = xmlNode.ChildNodes;
          foreach (XmlNode xn in nodes)
          {
            XmlElement xe = (XmlElement)xn;
            resXml[xe.Name] = xe.InnerText;//获取xml的键值对到WxPayData内部的数据中
          }
        }
        catch (Exception e)
        {
          Debug.Err(e);
          return null;
        }
        return resXml;
      }
      else
      {
        //默认传入JSON字符串
        return resStr.ToDictionary();
      }
    }
  }
}
